<template>
  <div>
    <!-- 三级分类的card -->
    <CategorySelect :show="!isShowTable" @getCategoryId="getCategoryId" />
    <!-- 动态展示属性的card -->
    <el-card>
      <div v-show="isShowTable">
        <el-button :disabled="!category3Id" class="addattrbtn" type="primary" icon="el-icon-plus" @click="addattr">添加属性</el-button>
        <!-- 展示动态属性的表格 -->
        <el-table :data="attrList" style="width: 100%" border>
          <el-table-column type="index" label="序号" align="center" width="80" />
          <el-table-column prop="attrName" label="属性名称" align="center" width="150" />
          <el-table-column prop="attrName" label="属性值列表" align="center">
            <template slot-scope="{ row }">
              <el-tag v-for="item in row.attrValueList" :key="item.id" type="success" width>{{ item.valueName }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="attrName" label="操作" align="center" width="200">
            <template slot-scope="{ row }">
              <el-button type="warning" size="mini" icon="el-icon-edit" @click="updateattr(row)">修改</el-button>
              <el-button type="danger" size="mini" icon="el-icon-delete" @click="deleteAttr(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 添加三级动态属性 -->
      <div v-show="!isShowTable">
        <el-form :inline="true" :model="attrInfo" class="demo-form-inline">
          <el-form-item label="属性名" value="">
            <el-input v-model.trim="attrInfo.attrName" placeholder="请输入属性名" />
          </el-form-item>
        </el-form>
        <el-button type="primary" :disabled="!attrInfo.attrName" @click="addattrValue">添加属性值</el-button>
        <el-button @click="isShowTable = true">取消</el-button>
        <el-table class="addattrtable" style="width: 100%" border :data="attrInfo.attrValueList">
          <el-table-column type="index" label="序号" width="80" align="center" />
          <el-table-column label="属性值名称">
            <template slot-scope="{ row, $index }">
              <!-- 这里结构需要用到span与input进行来回的切换 -->
              <el-input v-if="row.flag" :ref="$index" v-model="row.valueName" size="mini" placeholder="请输入属性值名称" @blur="inputBlurEvent(row)" @keyup.native.enter="row.flag = false" />
              <span v-else style="display: block" @click="spanShow(row, $index)">{{ row.valueName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="{ row, $index }">
              <!-- 这里气泡框需要加唯一标识,否则没有效果 -->
              <el-popconfirm ref="$index" :title="`确定要删除${row.valueName}吗?`" @onConfirm="deleteAttrValue($index)">
                <el-button slot="reference" size="mini" type="danger" icon="el-icon-delete" />
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" :disabled="attrInfo.attrValueList.length < 1" @click="addOrUpdateAttr">保存</el-button>
        <el-button @click="isShowTable = true">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script>
import { cloneDeep } from 'lodash'
export default {
  name: 'Attr',
  data() {
    return {
      category1Id: '',
      category2Id: '',
      category3Id: '',
      // attr动态属性数组
      attrList: [],
      // 这个属性控制动态属性table表格显示与隐藏
      isShowTable: true,
      // 收集新增属性 | 修改属性使用的对象
      attrInfo: {
        attrName: '', // 属性名
        attrValueList: [
          // 属性值,因为属性值可以有多个因此用数组,每一个属性值都是一个对象需要attrId,valueName
        ],
        categoryId: 0, // 三级分类的 id
        categoryLevel: 3, // 因为服务器也需要区分几级id
      },
    }
  },
  methods: {
    // 接收子组件自定义事件的回调函数
    getCategoryId({ id, level }) {
      // 解构出分类id,level是用来区分哪级的
      // console.log(id, level)
      switch (level) {
        case 1:
          // 赋值
          this.category1Id = id
          // 每次赋值后都清除掉上次的残留数据
          this.category2Id = ''
          this.category3Id = ''
          break
        case 2:
          this.category2Id = id
          this.category3Id = ''
          break
        case 3:
          this.category3Id = id
          this.getAttrList()
          break
      }
    },
    // 获取平台属性数据(整理好各分级的id,发起请求)
    async getAttrList() {
      //
      const { category1Id, category2Id, category3Id } = this
      const res = await this.$api.attr.reqGetAttrList(category1Id, category2Id, category3Id)
      console.log(res, 'attr动态属性')
      if (res.code === 200) {
        this.attrList = res.data
      }
    },
    // 动态添加三级属性值对象(点击添加属性值按钮事件回调)
    addattrValue() {
      this.attrInfo.attrValueList.push({
        // 获取三级分类id
        attrId: this.attrInfo.id,
        valueName: '',
        // flag属性:给每一个属性值添加一个标记flag,用于切换查看模式与编辑模式,好处,每一个属性值可以控制自己的模式切换
        flag: true,
      })
      this.$nextTick(() => {
        console.log(this)
        this.$refs[this.attrInfo.attrValueList.length - 1].focus()
      })
    },
    // 添加属性按钮
    addattr() {
      this.isShowTable = false
      // 目的:点击取消时候清除数据,顺便获取3级分类的id(重置对象了)
      this.attrInfo = {
        attrName: '', // 属性名
        attrValueList: [
          // 属性值,因为属性值可以有多个因此用数组,每一个属性值都是一个对象需要attrId,valueName
        ],
        // 对于修改某一个属性的时候,可以在已有的属性值基础上新增新的属性值、(在修改中新增属性值的时候需要把已有的属性的id带上)
        categoryId: this.category3Id, // 三级分类的 id
        categoryLevel: 3, // 因为服务器也需要区分几级id
      }
    },
    // 修改动态三级分类属性
    updateattr(row) {
      this.isShowTable = false
      // console.log(row)
      // this.attrInfo = row 这样写等于把从服务器获取回来的attrList[i]项,赋值给attrInfo,
      // 修改了attrInfo内的值等于修改了展示页面的attrList[row]项的值,
      // 所以需要使用深度克隆(用户真修改就不需要克隆了,就是怕用户修改了点击取消)
      this.attrInfo = cloneDeep(row)
      this.attrInfo.attrValueList.forEach((item) => {
        // 这样书写也可以给属性值添加flag,但是会发现视图不会跟着变化(因为这里动态添加的flag不是响应式数据)
        // item.flag = false // 这样写是非响应式
        // 因为Vue底层无法探测普通的新增 property,这样书写的属性并非响应式属性
        // 使用 set 方法
        // 第一个参数:监听的对象 第二个参数:添加新的响应式属性 第三参数: 新的属性的属性值
        this.$set(item, 'flag', false)
      })
    },
    // 离开三级分类文本框的回调事件
    inputBlurEvent(row) {
      // 针对点击修改时用户输入的无效字段(去空格)
      if (row.valueName) {
        row.valueName = row.valueName.trim()
      }
      console.log('离开了文本框进入展示模式')
      // 此时的row是attrValueList数组里的最后一项(也是最新的一项)
      // 不能为空
      if (row.valueName.trim() === '') return this.$message('不能为空')
      // 不能重复
      const result = this.attrInfo.attrValueList.some((item) => {
        // console.log(item, 'item')
        // 需要将 row 从数组里面判断的时候去除
        // row 最新新增的属性值【数组的最后一项元素】
        // 判断的时候,需要把已有的数组当中新增的这个属性值去除(去掉当前最新的row)
        if (row !== item) {
          // 得到一个布尔值
          return row.valueName.trim() === item.valueName.trim()
        }
      })
      // console.log(result)
      if (result) return this.$message('属性值不能重复')
      // 排除以上情况下才能变为编辑模式
      row.flag = false
      // console.log(row, 'row')
    },
    // 点击三级分类span标签的回调事件
    spanShow(row, index) {
      // 进入编辑模式
      row.flag = true
      console.log('点击了文本框进入编辑模式')
      // 获取 input 节点实现自动聚焦
      // 需要注意:点击span的时候,切换为input变为编辑模式,但是需要注意,对于浏览器而言,页面重绘与重排是耗时间的,点击span的时候,重绘重排一个input它是需要耗费时间的,因此我们不可能一点击span立马获取到input,
      // 解决方法 : $nextTick, 当节点渲染完毕了, 会执行一次
      this.$nextTick(() => {
        // console.log(this.$refs)
        // console.log(index)
        // console.log(this.$refs[index])
        this.$refs[index].focus()
      })
    },
    // 气泡确认框确定按钮的回调,删除动态属性
    deleteAttrValue(index) {
      // console.log('删除')
      this.attrInfo.attrValueList.splice(index, 1)
    },
    // 发请求保存三级属性回调
    async addOrUpdateAttr() {
      this.attrInfo.attrValueList = this.attrInfo.attrValueList.filter((item) => {
        // 过滤非空的属性
        if (item.valueName !== '') {
          // 删除掉多余数据
          delete item.flag
          // 写不写都行
          return true
        }
      })
      // if (!this.attrInfo.id && this.attrInfo.attrValueList < 1) {
      //   // 新增
      //   alert('新增,没有属性新增个毛线啊??')
      //   return
      // } else if (this.attrInfo.id && this.attrInfo.attrValueList < 1) {
      //   alert('删除操作???')
      //   // 进行删除的业务………………
      //   return
      // }
      try {
        // 发请求
        const res = await this.$api.attr.reqAddOrUpdateAttr(this.attrInfo)
        // 展示平台属性的面板
        this.isShowTable = true
        console.log(res)
        this.$message({ message: '保存成功', type: 'success' })
        // 保存成功后需要再次获取平台属性进行展示
        this.getAttrList()
      } catch (error) {
        console.log(error)
      }
    },
    // 删除整条三级属性
    deleteAttr(row) {
      this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          const res = await this.$api.attr.reqDeleteAttr(row.id)
          console.log(res)
          try {
            this.getAttrList()
          } catch (error) {
            console.log(error)
          }
          this.$message({
            type: 'success',
            message: '删除成功!',
          })
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除',
          })
        })
    },
  },
}
</script>

<style scoped>
.el-tag {
  margin: 5px;
}
.addattrbtn {
  margin-bottom: 20px;
}
.addattrtable {
  margin: 20px 0;
}
</style>
